//package hasthi.container;
//
//import hasthi.common.HasthiError;
//import hasthi.common.HasthiException;
//import hasthi.common.Utils;
//import hasthi.common.HasthiException.FaultCode;
//import hasthi.common.constants.HasthiConstants;
//
//import java.io.IOException;
//import java.io.InterruptedIOException;
//import java.net.InetSocketAddress;
//import java.net.URI;
//import java.net.URISyntaxException;
//import java.util.concurrent.Semaphore;
//import java.util.concurrent.TimeUnit;
//
//import org.apache.commons.logging.Log;
//import org.apache.commons.logging.LogFactory;
//import org.apache.http.HttpEntity;
//import org.apache.http.HttpException;
//import org.apache.http.HttpRequest;
//import org.apache.http.HttpResponse;
//import org.apache.http.HttpStatus;
//import org.apache.http.HttpVersion;
//import org.apache.http.impl.DefaultConnectionReuseStrategy;
//import org.apache.http.impl.nio.DefaultClientIOEventDispatch;
//import org.apache.http.impl.nio.reactor.DefaultConnectingIOReactor;
//import org.apache.http.message.BasicHttpEntityEnclosingRequest;
//import org.apache.http.message.BasicRequestLine;
//import org.apache.http.nio.NHttpConnection;
//import org.apache.http.nio.protocol.BufferingHttpClientHandler;
//import org.apache.http.nio.protocol.EventListener;
//import org.apache.http.nio.protocol.HttpRequestExecutionHandler;
//import org.apache.http.nio.reactor.ConnectingIOReactor;
//import org.apache.http.nio.reactor.IOEventDispatch;
//import org.apache.http.nio.reactor.IOReactorException;
//import org.apache.http.nio.reactor.SessionRequest;
//import org.apache.http.nio.reactor.SessionRequestCallback;
//import org.apache.http.params.BasicHttpParams;
//import org.apache.http.params.CoreConnectionPNames;
//import org.apache.http.params.CoreProtocolPNames;
//import org.apache.http.params.HttpParams;
//import org.apache.http.protocol.BasicHttpProcessor;
//import org.apache.http.protocol.ExecutionContext;
//import org.apache.http.protocol.HTTP;
//import org.apache.http.protocol.HttpContext;
//import org.apache.http.protocol.RequestConnControl;
//import org.apache.http.protocol.RequestContent;
//import org.apache.http.protocol.RequestExpectContinue;
//import org.apache.http.protocol.RequestTargetHost;
//import org.apache.http.protocol.RequestUserAgent;
//import org.apache.xmlbeans.XmlObject;
//import org.xmlpull.v1.builder.XmlBuilderException;
//import org.xmlpull.v1.builder.XmlDocument;
//import org.xmlpull.v1.builder.XmlElement;
//
//import xsul.XmlConstants;
//import xsul.XsulException;
//import xsul.soap.SoapUtil;
//import xsul.soap11_util.Soap11Util;
//import xsul.soap12_util.Soap12Util;
//import xsul.ws_addressing.WsaMessageInformationHeaders;
//import xsul.xbeans_util.XBeansUtil;
//
//public class NHttpClient {
//    protected static Log log = LogFactory.getLog(HasthiConstants.AGENT_LOGGER_NAME);
//    public final static String REQUEST_DATA = "RequestData";
//    private ConnectingIOReactor ioReactor;
//
//    
//    
//    public void start() throws HasthiException {
//        try {
//            HttpParams params = new BasicHttpParams();
//            params.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, 5000).setIntParameter(
//                    CoreConnectionPNames.CONNECTION_TIMEOUT, 10000).setIntParameter(
//                    CoreConnectionPNames.SOCKET_BUFFER_SIZE, 8 * 1024).setBooleanParameter(
//                    CoreConnectionPNames.STALE_CONNECTION_CHECK, false).setBooleanParameter(
//                    CoreConnectionPNames.TCP_NODELAY, true).setParameter(CoreProtocolPNames.USER_AGENT,
//                    "HttpComponents/1.1");
//
//            ioReactor = new DefaultConnectingIOReactor(2, params);
//
//            BasicHttpProcessor httpproc = new BasicHttpProcessor();
//            httpproc.addInterceptor(new RequestContent());
//            httpproc.addInterceptor(new RequestTargetHost());
//            httpproc.addInterceptor(new RequestConnControl());
//            httpproc.addInterceptor(new RequestUserAgent());
//            httpproc.addInterceptor(new RequestExpectContinue());
//
//            BufferingHttpClientHandler handler = new BufferingHttpClientHandler(httpproc,
//                    new MyHttpRequestExecutionHandler(),
//                    new DefaultConnectionReuseStrategy(), params);
//
//            handler.setEventListener(new EventLogger());
//
//            final IOEventDispatch ioEventDispatch = new DefaultClientIOEventDispatch(handler, params);
//
//            Thread t = new Thread(new Runnable() {
//
//                public void run() {
//                    try {
//                        ioReactor.execute(ioEventDispatch);
//                    } catch (InterruptedIOException ex) {
//                        System.err.println("Interrupted");
//                    } catch (IOException e) {
//                        System.err.println("I/O error: " + e.getMessage());
//                    }
//                    System.out.println("Shutdown");
//                }
//
//            });
//            t.start();
//            //Thread.sleep(1000);
//        } catch (IOReactorException e) {
//            throw new HasthiException(e,FaultCode.InitalizationError);
////        } catch (InterruptedException e) {
////            throw new HasthiException(e,FaultCode.InitalizationError);
//        }
//    }
//
//    public XmlObject sendReceive(MessageContext message) throws HasthiException {
//        try {
//            XmlElement request = XBeansUtil.xmlObjectToXmlElement(message.getRequest());
//            if(request == null){
//                throw new UnsupportedOperationException("REST requests are not yet supported");
//            }
//            
//            SoapUtil util = Soap12Util.getInstance();
//            XmlDocument soapRequest = util.wrapBodyContent(request);
//            WsaMessageInformationHeaders headers = new WsaMessageInformationHeaders(soapRequest);
//            headers.setTo(new URI(message.getSoapEndpoint()));
//            headers.setAction(new URI(message.getSoapAction()));
//            
//            URI uri = new URI(message.getSoapEndpoint());
//            String path = uri.getPath();
//            if(path == null || path.trim().length() == 0){
//                path = "/";
//            }
//            //System.out.println("path="+uri.getPath());
//            BasicHttpEntityEnclosingRequest httprequest 
//                = new BasicHttpEntityEnclosingRequest(new BasicRequestLine("POST",path,HttpVersion.HTTP_1_1));
//            httprequest.setEntity(new NonBlockingSoapContainer.XSULHttpEntity(soapRequest,false));
//            
//            //httprequest.setHeader(HTTP.CONTENT_TYPE,"text/xml");
//            //httprequest.setHeader(HTTP.CONTENT_ENCODING ,HTTP.UTF_8);
//            RequestData data = new RequestData(httprequest);
//            int port = uri.getPort(); 
//            if(port <= 0){
//                port = 80;
//            }
//            SessionRequest req = ioReactor.connect(new InetSocketAddress(uri.getHost(), port), null,
//                    data, data);
//            if(data.semaphore.tryAcquire(1000000, TimeUnit.MILLISECONDS)){
//                if(data.hasFault){
//                    throw data.error; 
//                }else{
//                    return data.response;
//                }
//                
//            }else{
//                throw new HasthiException("timeout waiting for response",FaultCode.ErrorAtClientWhileWsCall);
//            }
//        } catch (XmlBuilderException e) {
//            throw new HasthiException(e,FaultCode.ErrorAtClientWhileWsCall);
//        } catch (XsulException e) {
//            throw new HasthiException(e,FaultCode.ErrorAtClientWhileWsCall);
//        } catch (URISyntaxException e) {
//            throw new HasthiException(e,FaultCode.ErrorAtClientWhileWsCall);
//        } catch (InterruptedException e) {
//            throw new HasthiException(e,FaultCode.ErrorAtClientWhileWsCall);
//        } catch (HasthiException e) {
//            throw new HasthiException(e,FaultCode.ErrorAtClientWhileWsCall);
//        }
//    }
//
//    static class MyHttpRequestExecutionHandler implements HttpRequestExecutionHandler {
//        //private Map<HttpHost, LinkedList<HttpRequest>> requestMap = new ConcurrentHashMap<HttpHost, LinkedList<HttpRequest>>();
//
//        public MyHttpRequestExecutionHandler() {
//            super();
//        }
//
////        public void addRequest(HttpHost key, HttpRequest request) {
////            LinkedList<HttpRequest> list = requestMap.get(key);
////            if (list == null) {
////                list = new LinkedList<HttpRequest>();
////                requestMap.put(key, list);
////            }
////            list.add(request);
////        }
//
//        public void initalizeContext(final HttpContext context, final Object attachment) {
//            RequestData requestData = (RequestData) context
//                    .getAttribute(REQUEST_DATA);
//            if (requestData != null) {
//                throw new HasthiError("Http context overlaps");
//            }
//            context.setAttribute(REQUEST_DATA, attachment);
//        }
//
//        public void finalizeContext(final HttpContext context) {
//        }
//
//        public HttpRequest submitRequest(final HttpContext context) {
//            RequestData requestData = (RequestData) context
//                    .getAttribute(REQUEST_DATA);
//            if (requestData != null) {
//                if(requestData.requestSent == true){
//                    return null;
//                }else{
//                    requestData.requestSent = true;
//                    return requestData.request;
//                }
//            } else {
//                throw new HasthiError("Request data must not be null");
//            }
//        }
//
//        public void handleResponse(final HttpResponse response, final HttpContext context) {
//            RequestData requestData = (RequestData) context.getAttribute(REQUEST_DATA);
//            //BasicHttpEntityEnclosingRequest request = (BasicHttpEntityEnclosingRequest)context.getAttribute(ExecutionContext.HTTP_REQUEST);
//            
//            if (requestData == null) {
//                throw new HasthiError("Request data must not be null");
//            }
//            try {
//                HttpEntity entity = response.getEntity();
//
//                org.apache.http.StatusLine statusLine = response.getStatusLine();
//                if (statusLine.getStatusCode() == HttpStatus.SC_ACCEPTED) {
//                    requestData.hasFault = false;
//                } else if (statusLine.getStatusCode() == HttpStatus.SC_OK) {
//                    XmlDocument soapResponse = XmlConstants.BUILDER.parseInputStream(entity
//                            .getContent());
//                    // Utils.prettyPrint(soapResponse.getDocumentElement());
//                    SoapUtil[] utils = new SoapUtil[] { Soap11Util.getInstance(),
//                            Soap12Util.getInstance() };
//                    SoapUtil util = SoapUtil.selectSoapFragrance(soapResponse, utils);
//                    XmlElement result = util.requiredBodyContent(soapResponse);
//                    XmlObject responseAsXbeans = XBeansUtil.xmlElementToXmlObject(result);
//
//                    if (SOAPUtils.isFaultMessage(responseAsXbeans)) {
//                        requestData.error = HasthiException.buildException(responseAsXbeans);
//                        requestData.hasFault = true;
//                    } else {
//                        requestData.response = responseAsXbeans;
//                    }
//                } else if (statusLine.getStatusCode() == HttpStatus.SC_INTERNAL_SERVER_ERROR) {
//                    String message = Utils.readFromStream(entity.getContent());
//                    requestData.error = new HasthiException("Internal Server Error, 500 "+ message,FaultCode.ErrorAtClientWhileWsCall);
//                    requestData.hasFault = true;
//                }else{
//                    String message = Utils.readFromStream(entity.getContent());
//                    requestData.error = new HasthiException("Unknown Status Code "+ statusLine.getStatusCode()+ " "+ message,FaultCode.ErrorAtClientWhileWsCall);
//                    requestData.hasFault = true;
//                }
//            } catch (Throwable e) {
//                requestData.hasFault = true;
//                requestData.error = new HasthiException(e, FaultCode.ErrorAtClientAfterWsCall);
//            } finally {
//                requestData.semaphore.release();
//            }
//        }
//
//    }
//
//    static class EventLogger implements EventListener {
//
//        public void connectionOpen(final NHttpConnection conn) {
//            // System.out.println("Connection open: " + conn);
//        }
//
//        public void connectionTimeout(final NHttpConnection conn) {
//            // System.out.println("Connection timed out: " + conn);
//        }
//
//        public void connectionClosed(final NHttpConnection conn) {
//            // System.out.println("Connection closed: " + conn);
//        }
//
//        public void fatalIOException(final IOException ex, final NHttpConnection conn) {
//            System.err.println("I/O error: " + ex.getMessage());
//        }
//
//        public void fatalProtocolException(final HttpException ex, final NHttpConnection conn) {
//            System.err.println("HTTP error: " + ex.getMessage());
//            log.error(ex);
//        }
//
//    }
//    
//    
//
//    public class RequestData implements SessionRequestCallback{
//        HttpRequest request;
//        XmlObject response;
//        Semaphore semaphore;
//        boolean requestSent;
//        boolean hasFault;
//        HasthiException error;
//
//        public RequestData(HttpRequest request) {
//            semaphore = new Semaphore(0);
//            this.request = request;
//            requestSent = false;
//        }
//        
//        public void handleFaluire(SessionRequest request){
//            hasFault =true;
//            error = new HasthiException(request.getException(),FaultCode.ErrorAtClientWhileWsCall);
//            semaphore.release();
//        }
//        
//
//        public void cancelled(SessionRequest request) {
//            handleFaluire(request);
//            
//        }
//
//        public void completed(SessionRequest request) {
//            // TODO Auto-generated method stub
//            
//        }
//
//        public void failed(SessionRequest request) {
//            handleFaluire(request);
//            
//        }
//
//        public void timeout(SessionRequest request) {
//            handleFaluire(request);
//        }
//    }
//    
//    public void shutDown() throws IOException{
//        ioReactor.shutdown();
//    }
//
//}
